package com.lj.cloudDisk.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lj.cloudDisk.config.exception.SpaceException;
import com.lj.cloudDisk.mapper.FileMapper;
import com.lj.cloudDisk.mapper.UserDirMapper;
import com.lj.cloudDisk.pojo.File;
import com.lj.cloudDisk.pojo.TreeNode;
import com.lj.cloudDisk.pojo.UserDir;
import com.lj.cloudDisk.service.FileService;
import com.lj.cloudDisk.service.UserDirService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户目录
 */
@Service
@Slf4j
public class UserDirServiceImpl extends ServiceImpl<UserDirMapper,UserDir> implements UserDirService {


    @Autowired
    UserDirMapper userDirMapper;

    @Autowired
    UserDirService userDirServiceBroker;

    @Autowired
    FileMapper fileMapper;

    @Autowired
    FileService fileService;

    //获取当前修改文件位置
    private static int result = 1;

    /**
     * 获取用户目录树
     * @param id
     * @return
     */
    @Override
    public UserDir getUserDir(String id) {
        LambdaQueryWrapper<UserDir> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserDir::getMemId,id);
        UserDir userDir = userDirMapper.selectOne(queryWrapper);
        return userDir;
    }

    @Transactional
    public void updateUserDir(UserDir userDir,String userId){
        //更新目录结构
        LambdaQueryWrapper<UserDir> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserDir::getMemId,userId);
        userDirMapper.update(userDir,queryWrapper);

    }

    /**
     *
     * @param userId 用户id
     * @param createdName 文件夹名称
     * @param currentFolderId 目前所处文件id
     */

    @Override
    public UserDir setDirStruct(String userId, String createdName, Long currentFolderId) {

        //获取当前用户目录结果
        UserDir userDir = getUserDir(userId);
        TreeNode userTreeNode = JSON.parseObject(userDir.getMemDir(), new TypeReference<TreeNode>(){});
        TreeNode treeNode = new TreeNode();

        treeNode.setName(createdName+"/");
        treeNode.setParentId(currentFolderId);
        treeNode.setChildrenList(new ArrayList<>());

        //判断当前文件名是否重复
        List<TreeNode> childrenList= new ArrayList<>();
        if(userTreeNode.getId() == currentFolderId){
             childrenList = (userTreeNode.getChildrenList());
         }else {
            findTreeNode(userTreeNode,currentFolderId,childrenList);
        }

        List listName = new ArrayList<>();
        listName = childrenList.stream().map((item) ->{
          return  item.getName();
        }).collect(Collectors.toList());
        listName.add(treeNode.getName());
        System.out.println(listName.toString());
        Set nameSet = new HashSet<>(listName);
        if(listName.size() != nameSet.size()){
            throw new SpaceException(20001,"当前文件与其他文件夹重名");
        }

        //插入文件夹
        if (userTreeNode.getId() != currentFolderId) {
            addTreeNode(userTreeNode,currentFolderId,treeNode);
        } else {
            userTreeNode.getChildrenList().add(treeNode);
        }

        String treeNodeJson = JSON.toJSONString(userTreeNode);

        userDir.setMemDir(treeNodeJson);

        //更新目录结构
        userDirServiceBroker.updateUserDir(userDir,userId);

         return userDir;

    }

    /**
     * @param userId 用户id
     * @param rename 文件夹名
     * @param folderId 文件夹id
     * @return
     */
    @Transactional
    @Override
    public UserDir renameFolder(String userId, String rename, Long folderId,String url) {
        if(rename.equals("/")){
            throw new SpaceException(20001,"文件夹名不能为空");
        }
        //获取用户目录结构
        UserDir userDir = getUserDir(userId);
        TreeNode userTreeNode = JSON.parseObject(userDir.getMemDir(),new TypeReference<TreeNode>(){});
        //判断当前文件名是否重复
        List<TreeNode> childrenList= new ArrayList<>();
        if(userTreeNode.getId() == folderId){
            childrenList = (userTreeNode.getChildrenList());
        }else {
            findTreeNode(userTreeNode,folderId,childrenList);
        }

        List listName = new ArrayList<>();
        listName = childrenList.stream().map((item) ->{
            return  item.getName();
        }).collect(Collectors.toList());
        listName.add(rename);

        System.out.println(listName.toString());
        Set nameSet = new HashSet<>(listName);
        if(listName.size() == nameSet.size()){
            throw new SpaceException(20001,"当前文件与其他文件夹重名");
        }

        updateTreeNode(userTreeNode,folderId,rename,1);

        //更新目录
        userDir.setMemDir(JSON.toJSONString(userTreeNode));
        try {
            userDirServiceBroker.updateUserDir(userDir,userId);

        } catch (Exception e) {
            throw new SpaceException(20001,"更新文件夹目录失败");
        }

        //更新文件目录
        List<File> fileList = null;
        try {
            fileList = getFileList(userId, url, rename, result);
            fileList.stream().forEach((item)->{
                fileService.updateFilePath(item);
            });
        } catch (Exception e) {
            throw new SpaceException(20001,"更新文件目录失败");
        }

        return userDir;
    }


    /**
     * 删除文件夹以及文件
     * @param userId
     * @param url
     * @param folderId
     * @return
     */
    @Override
    public UserDir delFolder(String userId, String url, Long folderId) {
        UserDir userDir = getUserDir(userId);
        TreeNode userTreeNode = JSON.parseObject(userDir.getMemDir(),new TypeReference<TreeNode>(){});
        //删除目录
        findToDelTreeNode(userTreeNode,folderId);
        log.debug(userTreeNode.toString());

        userDir.setMemDir(JSON.toJSONString(userTreeNode));
        //删除文件
        fileService.deleteFile(userId,url);

        //更新数据库目录
        updateUserDir(userDir,userId);

        return userDir;
    }

    /**
     * 查询节点并删除
     * @param userTreeNode
     * @param folderId
     */
    private void findToDelTreeNode(TreeNode userTreeNode, Long folderId) {
        List<TreeNode> list = userTreeNode.getChildrenList();
        if (list == null || list.isEmpty()) {
            return;
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (folderId == list.get(i).getId()) {
                    list.remove(i);
                } else {
                    findToDelTreeNode(list.get(i),folderId);
                }
            }
        }
    }


    /**
     * 查询父节点为parentId获取下一级文件夹
     * @param treeNode
     * @param parentId
     * @param childrenList
     */
    private static void findTreeNode(TreeNode treeNode, Long parentId, List childrenList) {


        List<TreeNode> list = treeNode.getChildrenList();
        if (list == null || list.isEmpty()) {
            return;
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId() == parentId) {
                    childrenList = list.get(i).getChildrenList();
                    return;
                } else {
                    findTreeNode(list.get(i), parentId, childrenList);
                }
            }
        }
    }

    /**
     * 增加文件夹
     * @param treeNode
     * @param id 当前目录
     * @param newNode 插入文件夹
     */
    private static void addTreeNode(TreeNode treeNode, Long id,TreeNode newNode) {


        List<TreeNode> list = treeNode.getChildrenList();
        if (list == null || list.isEmpty()) {
            return;
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId() == id) {
                     list.get(i).getChildrenList().add(newNode);
                    return;
                } else {
                    addTreeNode(list.get(i),id,newNode);
                }
            }
        }
    }


    /**
     * 更新文件
     * @param treeNode
     * @param id 当前目录
     * @param rename 文件夹名
     */
    private static void updateTreeNode(TreeNode treeNode, Long id,String rename,int count) {

        if(treeNode.getId() == id){
           treeNode.setName(rename);
           result = count;
           return;
        }

        List<TreeNode> list = treeNode.getChildrenList();
        if (list == null || list.isEmpty()) {
            return;
        } else {
            for (int i = 0; i < list.size(); i++) {
                    updateTreeNode(list.get(i),id,rename,count + 1);
                }

        }


    }

    /**
     * 获取文件路径 并跟新文件路径
     * @param memId
     * @param url
     * @param rename
     * @param result
     * @return
     */
    private  List<File>  getFileList(String memId,String url,String rename,int result){
            LambdaQueryWrapper<File> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(File::getMemId,memId);
            queryWrapper.like(File::getFDir,url);
            List<File> files = fileMapper.selectList(queryWrapper);

        for (int i = 0; i < files.size(); i++) {
            String fDir = files.get(i).getFDir();
            String[] dir = fDir.split("/",-1);
            log.debug(Arrays.toString(dir));
            log.debug(dir[result]);
            dir[result] = rename.substring(0,rename.length()-1);
            StringBuffer stringBuffer = new StringBuffer();
            for (int j = 1; j < dir.length; j++) {
                stringBuffer.append("/").append(dir[j]);
                log.debug(stringBuffer.toString());
            }

            files.get(i).setFDir(stringBuffer.toString());

        }

        return files;

    }



}
